/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright(c) 2000 - 2001 Intel Corporation. All Rights Reserved.
//
//  VSS: 
//     $Workfile: $
//     $Revision: $
//     $Date:     $
//     $Archive:  $
//
//  Description:
//      Intel(R) Integrated Performance Primitives - JPEG Helper file.
//      This file contains Huffman encoding (Baseline) functions.
//
//  History:
//     Date         Author        Changes
//     2000/5/22   Jerry Hu       Created (Version 0.1 Baseline)
//
********************************************************************************/
#include "_ippjpeg.h"
#include "ijehufsh.h"


/******************************************************************************
// Name:             ippiEncodeHuffman_Direct_JPEG_16s1u
// Description:      Encods 8x8 block coefficients.
// Input Arguments: 
//             pSrc: Identifies source coefficient data in 8x8.
//      pDstBitsLen: Indicates the number of bits that have been Encoded before.
//          pDCPred: Identifies the previous DC value of prediction.
//     pDCHuffTable: Identifies "IppJPEGDeHuffTable" data structure for DC decoding.
//     pACHuffTable: Identifies "IppJPEGDeHuffTable" data structure for AC decoding.
//
// Output Arguments:
//             pDst: Identifies source huffman stream data.
//      pDstBitsLen: Indicates the number of bits that have been Encoded after this function calling.
//          pDCPred: Identifies the current DC value of prediction.
//
// Remarks:      
//                   1. The start address of "pSrc" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   3. *pDCPred shall be 0 in initial or after each restart interval.
//
// Returns:         
//    IPP_STATUS_OK: Succeeds.
// IPP_STATUS_ERROR: Encoding error.
******************************************************************************/
IPPFUN(IppStatus, ippiEncodeHuffman_Direct_JPEG_16s1u) (const Ipp16s *pSrc,
                                                 Ipp8u        *pDst,  
                                                 int          *pDstBitsLen,
                                                 Ipp16s       *pDCPred,
                                                 const IppJPEGEnHuffTable 
                                                              *pDCHuffTable,
                                                 const IppJPEGEnHuffTable 
                                                              *pACHuffTable)

{
    int    rrrr;
    int    ssss;
    int    rs;
    int    data;
    int    i;
    int    val;
    int    nbits;

    _IPP_CHECK_ARG((NULL!=pSrc)&&(NULL!=pDst));
    _IPP_CHECK_ARG((NULL!=pDstBitsLen)&&(0<=*pDstBitsLen));
    _IPP_CHECK_ARG(NULL!=pDCPred);
    _IPP_CHECK_ARG((NULL!=pDCHuffTable)&&(NULL!=pACHuffTable));

    /* Set 0 to invliad bits in the first Ipp8u. */
    //pDst[*pDstBitsLen>>3]&=(0xff<<(8-(*pDstBitsLen&7)));

    /*
    // Encode DC Coefficient
    */

    data = pSrc[0] - *pDCPred;
    _CSIZE(ssss, data);
    *pDCPred = pSrc[0];

    /* Encode Size of DC Coefficient */
    val   = pDCHuffTable->huffCode[ssss];
    nbits = pDCHuffTable->huffSize[ssss];

    _IppWriteStreamBits(val, nbits, pDst, pDstBitsLen);

    /* Encode DC Coefficient Value */
    _IppWriteStreamBits(data,ssss, pDst, pDstBitsLen);


    /*
    // Encode AC Coefficient(s)
    */

    rrrr = 0;

    for (i=1; i<64; i++) {
        data = pSrc[_nIppIZigZagIndex[i]];
        if (0==data) {
           rrrr++; /* Increment run-length of zeroes */
           continue;
        } 

        while (rrrr>15) {
            val   = pACHuffTable->huffCode[0xf0];
            nbits = pACHuffTable->huffSize[0xf0];
            /* Encode zeros */
            _IppWriteStreamBits(val, nbits, pDst, pDstBitsLen);
            rrrr-=16;
        }

        _CSIZE(ssss, data);

        rs=(rrrr<<4)+ssss;

        val   = pACHuffTable->huffCode[rs];
        nbits = pACHuffTable->huffSize[rs];
        _IppWriteStreamBits(val, nbits, pDst, pDstBitsLen);
        _IppWriteStreamBits(data,ssss, pDst, pDstBitsLen);
        rrrr = 0;
    }   /* for (i=1; i<IPPJPEG_BLOCKLEN; i++) */

    if (rrrr > 0) {
        /* Write EOB */
        val   = pACHuffTable->huffCode[0x0];
        nbits = pACHuffTable->huffSize[0x0];
        _IppWriteStreamBits(val, nbits, pDst, pDstBitsLen);
    }

    return IPP_STATUS_OK;
}

/* EOF */
